package com.fingard.dsp.bank.directbank.allinpay02;

import com.alibaba.fastjson.JSONObject;
import com.allinpay.ets.client.SecurityUtil;
import com.allinpay.ets.client.StringUtil;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.SendBankRespose;
import com.fingard.dsp.bank.directbank.bankInterface.IStatement;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.statement.ReqQryStatement;
import com.fingard.dsp.bank.reqrespobj.statement.RetAtsStatement;
import com.fingard.dsp.bank.reqrespobj.statement.TransState;
import com.fingard.dsp.bank.reqrespobj.statement.detail.RetAtsStatementDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.*;
import com.fingard.text.SplitHelper;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.TreeMap;

public class AllInPay02Statement extends AllInPay02Base implements IStatement {
    public RetAtsStatement d_Qry_Statement(ReqQryStatement p_reqQrySttm) throws Exception {
        RetAtsStatement retAts = new RetAtsStatement(p_reqQrySttm);
        retAts.writeStart();

        String[] unifiedOrderRespHeader = new String[]{"", ""};
        String unifiedOrderTotalNum = "0";
        String[] gatewayRespHeader = new String[]{"", ""};
        String gatewayTotalNum = "0";
        String[] trxFileRespHeader = new String[]{"", ""};
        String trxFileTotalNum = "0";
        String[] tmpPosRecRespHeader = null;
        String tmpPosRecTotalNum = "0";
        if ("S".equals(p_reqQrySttm.statementType)) {
            // 公众号/一码付收款对账单
            unifiedOrderRespHeader = getUnifiedOrderStatement(p_reqQrySttm, retAts);
            unifiedOrderTotalNum = retAts.totalNum;

            // 网关支付对账单
            gatewayRespHeader = getGatewayStatement(p_reqQrySttm, retAts);
            gatewayTotalNum = retAts.totalNum;

            //扫码及网关支付对账单
            trxFileRespHeader = getTrxFileStatement(p_reqQrySttm, retAts);
            trxFileTotalNum = retAts.totalNum;

            tmpPosRecRespHeader = getPosRecStatement(p_reqQrySttm, retAts);
            tmpPosRecTotalNum = retAts.totalNum;
        }

        // 获取代收付对账单
        String[] payRecRespHeader = getPayRecStatement(p_reqQrySttm, retAts);
        String payRecTotalNum = retAts.totalNum;
        if ("".equals(payRecTotalNum)) {
            payRecTotalNum = "0";
        }

        if (unifiedOrderRespHeader[0].equals("-1") && gatewayRespHeader[0].equals("-1") && payRecRespHeader[0].equals("-1") && tmpPosRecRespHeader[0].equals("-1") && trxFileRespHeader[0].equals("-1")) {
            String respInfo = "公众号/一码付对账单获取失败,原因:[" + unifiedOrderRespHeader[1] + "];"
                    + "网关对账单获取失败,原因:[" + gatewayRespHeader[1] + "];"
                    + "POS对账单获取失败,原因:[" + tmpPosRecRespHeader[1] + "];"
                    + "实时收付对账单获取失败,原因:[" + payRecRespHeader[1] + "];"
                    + "收银宝扫码/网关对账单获取失败,原因:[" + trxFileRespHeader[1] + "];";

            retAts.writeRespCode("-1");
            retAts.writeRespInfo(respInfo);
        } else {
            if (retAts.getWrittenRdCount() == 0) {
                retAts.writeRespCode("0");
                String respInfo = unifiedOrderRespHeader[1];
                if (StringHelper.isNullOrEmpty(respInfo) && gatewayRespHeader != null) {
                    respInfo = gatewayRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo) && payRecRespHeader != null) {
                    respInfo = payRecRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo) && tmpPosRecRespHeader != null) {
                    respInfo = tmpPosRecRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo) && trxFileRespHeader != null) {
                    respInfo = trxFileRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = "交易为空";
                }
                retAts.writeRespInfo(respInfo);
            } else {
                // 获取成功时写入总笔数
                int totalNum = Integer.parseInt(unifiedOrderTotalNum) + Integer.parseInt(gatewayTotalNum) + Integer.parseInt(payRecTotalNum) + Integer.parseInt(tmpPosRecTotalNum) + Integer.parseInt(trxFileTotalNum);
                retAts.isWritedTotalNum(String.valueOf(totalNum));
            }
        }

        retAts.writeEnd();
        return retAts;
    }

    private String[] getGatewayStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] respHeader = new String[]{"", ""};

        String respCode = "";
        String respInfo = "";

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "gateway");
            if (actItem != null) {
                String mchtCd = actItem.merchantId;
                String settleDate = Format.Date10Format.format(p_reqQrySttm.getBusDate());
                String signMsg = "";

                String waitSignData = mchtCd + settleDate + actItem.saltKey;
                WriteBankLogLn2("通联网关支付对账单签名原始数据:" + waitSignData);

                signMsg = SecurityUtil.MD5Encode(waitSignData);

                String reqPostData = "mchtCd=" + mchtCd + "&settleDate=" + settleDate + "&signMsg=" + signMsg;
                WriteBankLogLn2("发送通联网关支付对账单请求数据:" + reqPostData);

                String submitURL = bankFront.getUrl("gatewayStatement");
                WriteBankLogLn2("通联网关支付对账单下载服务地址:" + submitURL);

                // 发送通联
                int flag = 0;
                StringBuffer srcStr = new StringBuffer();
                String respSignMsg = "";

                int timeout = this.getReadTimeout(120);
                WriteBankLogLn2("超时时间:" + timeout + "毫秒");

                //URL url = new URL();
                HttpURLConnection httpConn = new AllInPay02Statement().getHttpsURLConnection(submitURL + "?" + reqPostData);
                httpConn.setReadTimeout(timeout);
                httpConn.connect();
                BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
                String lines;
                while ((lines = reader.readLine()) != null) {
                    if (lines.indexOf("ERRORCODE") >= 0) {
                        WriteBankLogLn2("通联网关支付对账单响应内容:" + lines);

                        String errCode = lines.substring(lines.length() - 1);

                        respCode = "-1";
                        respInfo = convertErrToAts(errCode);

                        respHeader[0] = respCode;
                        respHeader[1] = lines + "+" + respInfo;

                        return respHeader;
                    }
                    // 获取响应签名
                    if (flag == 1) {
                        respSignMsg = lines;
                        break;
                    }
                    // 获取对账单响应明细数据
                    if (lines.length() > 0) {
                        srcStr.append(lines + "\r\n");
                    } else {
                        flag = 1;
                    }

                }
                reader.close();
                httpConn.disconnect();

                WriteBankLogLn2("通联网关支付对账单响应数据:" + srcStr.toString());

                int count = 0;

                boolean verifybool = verifySign(srcStr.toString(), respSignMsg, actItem);
                if (verifybool) {
                    /**
                     *  第一行为汇总信息：
                     *      0      1      2        3       4       5       6       7      8
                     结算日期|批次号|交易笔数|成功笔数|交易金额|退款笔数|退款金额|手续费|清算金额

                     第二行开始为交易明细：
                     0       1      2      3         4         5         6      7       8     9         10
                     交易类型|结算日期|商户号|交易时间|商户订单号|通联订单号|交易金额|手续费|清算金额|币种|商户原始订单金额(分)

                     文件最后为签名信息，与交易明细间有一空行。
                     */
                    StringReader tmpStrReader = new StringReader(srcStr.toString());
                    BufferedReader tmpBuferReader = new BufferedReader(tmpStrReader);

                    // 获取总笔数
                    String totalLine = tmpBuferReader.readLine();
                    String[] totalArray = totalLine.split("|");

                    retAts.totalNum = totalArray[3];
                    WriteBankLogLn2("通联网关支付对账单成功总笔数:" + totalArray[3]);

                    // 获取明细数据
                    while (true) {
                        String eachline = tmpBuferReader.readLine();
                        if (eachline == null) {
                            break;
                        }

                        String[] eachNodes = eachline.split("|");
                        if (StringHelper.hasAnyChar(eachNodes[0])) {
                            /*
                             * 交易类型：
                             *     ZF：支付成功
                             *	   TH: 退款，通联系统扎差成功，退款请求发送到银行
                             *	   CX: 冲销成功，未能成功退款，资金已经退回给商户
                             */
                            if ("ZF".equals(eachNodes[0])) {
                                count++;

                                RetAtsStatementDetail p_retDetail = new RetAtsStatementDetail();

                                // 商户订单号
                                if (StringHelper.hasAnyChar(eachNodes[4])) {
                                    p_retDetail.askNumber = eachNodes[4];
                                }

                                // 交易时间
                                if (StringHelper.hasAnyChar(eachNodes[3])) {
                                    p_retDetail.busTime = Format.DateTime14Format.format(Format.DateTimeFormat.parse(eachNodes[3]));
                                }

                                p_retDetail.cdFlag = "22";

                                // 交易金额
                                if (StringHelper.hasAnyChar(eachNodes[6])) {
                                    p_retDetail.amount = StringHelper.amountDivide100(eachNodes[6]);
                                }

                                // 手续费
                                if (StringHelper.hasAnyChar(eachNodes[7])) {
                                    p_retDetail.fee = Format.DecimalAmtFormat.format(eachNodes[7]);
                                }

                                // 交易状态
                                p_retDetail.transState = TransState.Success;

                                retAts.writeRetDetail(p_retDetail);
                            }
                        }
                    }
                } else {
                    respCode = "-1";
                    respInfo = "通联响应对账单数据本地验签失败!";

                    respHeader[0] = respCode;
                    respHeader[1] = respInfo;

                    return respHeader;
                }

                retAts.totalNum = String.valueOf(count);
            } else {
                respCode = "-1";
                respInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户配置信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            respCode = "-1";
            respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        respHeader[0] = respCode;
        respHeader[1] = respInfo;

        return respHeader;
    }

    private String[] getUnifiedOrderStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] respHeader = new String[]{"", ""};

        String respCode = "";
        String respInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "unifiedorder");
            if (actItem != null) {
                String cusid = actItem.merchantId;
                String appid = actItem.appId;
                String date = Format.Date8Format.format(p_reqQrySttm.getBusDate());
                String randomstr = get_nonce_str();

                String sign = "";

                StringBuffer bufSignSrc = new StringBuffer();

                StringUtil.appendSignPara(bufSignSrc, "appid", appid);
                StringUtil.appendSignPara(bufSignSrc, "cusid", cusid);
                StringUtil.appendSignPara(bufSignSrc, "date", date);
                StringUtil.appendSignPara(bufSignSrc, "key", actItem.saltKey);
                StringUtil.appendLastSignPara(bufSignSrc, "randomstr", randomstr);

                // 签名
                String waitSignData = bufSignSrc.toString();
                WriteBankLogLn2("通联一码付/公众号对账单签名数据:\r\n" + waitSignData);

                sign = SecurityUtil.MD5Encode(waitSignData);

                String url = bankFront.getUrl("unifiedOrderStatement");
                WriteBankLogLn2("通联一码付/公众号对账单服务地址:" + url);

                HttpClient httpclient = new HttpClient();
                int timeout = this.getReadTimeout(120);
                WriteBankLogLn2("超时时间:" + timeout + "毫秒");
                httpclient.getHttpConnectionManager().getParams().setSoTimeout(timeout);
                PostMethod postmethod = new PostMethod(url);

                NameValuePair[] paramData = {
                        new NameValuePair("cusid", cusid),
                        new NameValuePair("appid", appid),
                        new NameValuePair("date", date),
                        new NameValuePair("randomstr", randomstr),
                        new NameValuePair("sign", sign)
                };

                postmethod.setRequestBody(paramData);

                WriteBankLogLn2("通联一码付/公众号对账单请求数据:\r\n" + getPostData(paramData));

                int responseCode = httpclient.executeMethod(postmethod);
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    String strResponse = URLDecoder.decode(postmethod.getResponseBodyAsString(), getCharset());
                    WriteBankLogLn2("通联一码付/公众号对账单响应数据:\r\n" + strResponse);

                    JSONObject respJson = JSONObject.parseObject(strResponse);

                    // 获取对账单地址成功
                    if ("SUCCESS".equals((String) respJson.get("retcode"))) {
                        String japiStatementURL = (String) respJson.get("url");
                        WriteBankLogLn2("通联一码付/公众号对账单文件地址:" + japiStatementURL);

                        WebRequest tmpWebRequest = new WebRequest(japiStatementURL);
                        tmpWebRequest.setConnectTimeout(timeout);
                        tmpWebRequest.setRequestProperty("connection", "Close");

                        String[] retStr = tmpWebRequest.upload(null, getCharset());

                        System.out.println("响应:" + retStr);

                        // 发送通联
                        StringBuffer srcStr = new StringBuffer();

                        //URL httpURL = new URL();
                        HttpURLConnection httpConn = new AllInPay02Statement().getHttpsURLConnection(japiStatementURL);
                        httpConn.setReadTimeout(timeout);
                        httpConn.connect();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
                        String lines;
                        while ((lines = reader.readLine()) != null) {
                            if (lines.length() > 0) {
                                srcStr.append(lines + "\r\n");
                            } else {
                                break;
                            }
                        }
                        reader.close();
                        httpConn.disconnect();

                        WriteBankLogLn2("通联一码付/公众号对账单文件数据:\r\n" + srcStr.toString());

                        // 解析公众号对账单详情数据
                        StringReader strReader = new StringReader(srcStr.toString());
                        BufferedReader tmpReader = new BufferedReader(strReader);

                        String line1 = tmpReader.readLine();
                        String[] columns = line1.split(",");

                        // 解析明细返回
                        while (true) {
                            String eachline = tmpReader.readLine();
                            if (eachline == null) {
                                break;
                            }

                            String[] values = eachline.split(",");
                            if (columns.length == values.length) {
                                HashMap<String, String> mapKV = SplitHelper.splitAsValueMap(columns, values);

                                if (mapKV.containsKey("交易类型")) {
                                    String transType = mapKV.get("交易类型");
                                    if ("消费".equals(transType) || "微信支付".equals(transType) || "支付宝支付".equals(transType) || "通联钱包消费".equals(transType)) {
                                        totalNum++;

                                        RetAtsStatementDetail retDetail = new RetAtsStatementDetail();

                                        // 商户订单号
                                        if (mapKV.containsKey("订单号")) {
                                            retDetail.askNumber = mapKV.get("订单号");
                                        }

                                        // 交易时间
                                        if (mapKV.containsKey("交易日期") && mapKV.containsKey("交易时间")) {
                                            String busiTime = mapKV.get("交易日期") + " " + mapKV.get("交易时间");
                                            retDetail.busTime = Format.DateTime14Format.format(Format.DateTimeFormat.parse(busiTime));
                                        }

                                        retDetail.cdFlag = "22";

                                        // 交易金额
                                        if (mapKV.containsKey("交易金额")) {
                                            retDetail.amount = Format.DecimalAmtFormat.format(mapKV.get("交易金额"));
                                        }

                                        // 手续费
                                        if (mapKV.containsKey("手续费")) {
                                            retDetail.fee = Format.DecimalAmtFormat.format(mapKV.get("手续费"));
                                        }

                                        // 交易状态
                                        retDetail.transState = TransState.Success;

                                        retAts.writeRetDetail(retDetail);
                                    }
                                }
                            } else {
                                break;
                            }
                        }
                    } else {
                        // 获取对账单地址失败
                        respCode = "-1";
                        respInfo = (String) respJson.get("retmsg");
                    }
                }
            } else {
                respCode = "-1";
                respInfo = "未找到账号[" + p_reqQrySttm.actNum + "]商户配置信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            respCode = "-1";
            respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        respHeader[0] = respCode;
        respHeader[1] = respInfo;

        return respHeader;
    }

    private String[] getPayRecStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] respHeader = new String[]{"", ""};

        String respCode = "";
        String respInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "unionRecPay");
            if (actItem != null) {
                if (getBankConfig().getValueAsBool("useFTPOrSFTP")) {
                    // 文件名规范：PDS+商户号+日期(yyyymmdd)+.txt
                    String busDate = Format.Date8Format.format(p_reqQrySttm.getBusDate());
                    String tmpDownFileName = "PDS" + actItem.merchantId + busDate + ".txt";
                    String tmpLocalMarkPath = createTempFileDirectory(busDate) + File.separator + "statement" + File.separator + tmpDownFileName;
                    WriteBankLogLn2("对账文件保存本地路径: " + tmpLocalMarkPath);

                    FtpSet ftpSet = bankFront.getFtpSet("payrecsttm");
                    MixFtp mixFtp = new MixFtp(ftpSet);
                    FtpReceiver ftpReceiver = mixFtp.downloadFileFromDir(ftpSet.downDir, tmpDownFileName, tmpLocalMarkPath);
                    if (ftpReceiver.isCompleted) {
                        String tmpRetStr = FileHelper.readFileText(tmpLocalMarkPath, getCharset());
                        WriteBankLogLn2("本地对账文件内容:\r\n" + tmpRetStr);
                        if (StringHelper.hasAnyChar(tmpRetStr)) {
                            respCode = "0";
                            StringReader strReader = new StringReader(tmpRetStr);
                            BufferedReader tmpReader = new BufferedReader(strReader);
                            tmpReader.readLine();

                            // 解析明细返回
                            while (true) {
                                String eachline = tmpReader.readLine();
                                if (StringHelper.isNullOrEmpty(eachline)) {
                                    break;
                                }
                                RetAtsStatementDetail tmpRetDetail = null;

                                String[] detailNodes = eachline.split(" ");
                                if (StringHelper.hasAnyChar(detailNodes[3])) {
                                    if ("0000".equals(detailNodes[3]) || "4000".equals(detailNodes[3])) {
                                        if ("F".equals(p_reqQrySttm.statementType)) {
                                            if ("0".equals(detailNodes[2])) {
                                                totalNum++;
                                                tmpRetDetail = writeDetailMsg(detailNodes);
                                            }
                                        } else if ("S".equals(p_reqQrySttm.statementType)) {
                                            if ("1".equals(detailNodes[2])) {
                                                totalNum++;
                                                tmpRetDetail = writeDetailMsg(detailNodes);
                                            }
                                        } else {
                                            totalNum++;
                                            tmpRetDetail = writeDetailMsg(detailNodes);
                                        }
                                        if (tmpRetDetail != null) {
                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    }
                                }
                            }
                        } else {
                            respCode = "-1";
                            respInfo = "本地对账文件内容为空!";
                        }
                    } else {
                        respCode = "-1";
                        respInfo = "对账文件下载失败:" + ftpReceiver.connMsg;
                    }
                } else if (StringHelper.hasAnyChar(actItem.qryStatementURL) && "post".equalsIgnoreCase(actItem.billRequestType)) {
                    // 金服宝POST方式对账单获取
                    AllInPay02Header header = new AllInPay02Header();
                    header.TRX_CODE = "200002";
                    header.REQ_SN = getQryTransID();
                    XmlTextWriter xmlWriter = new XmlTextWriter();
                    writeBatBillCommonHeader(xmlWriter, header, actItem);

                    xmlWriter.writeStartElement("BODY");
                    xmlWriter.writeStartElement("RECONF_DOWN");
                    xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
                    xmlWriter.writeElementString("DAY", p_reqQrySttm.busDate);
                    xmlWriter.writeElementString("SETTACCT", actItem.inMerchantId);
                    xmlWriter.writeEndDocument();

                    String[] tmpStrRet = sendBillToBank(xmlWriter.toXmlString(), actItem, header.REQ_SN);

                    if (tmpStrRet[0].length() == 0) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                        if (tmpBkReader != null) {
                            String tmpRetCode = tmpBkReader.getFirstText("/AIPG/HEAD/RET_CODE");
                            String tmpRetMsg = tmpBkReader.getFirstText("/AIPG/HEAD/RET_MSG");
                            if ("0000".equalsIgnoreCase(tmpRetCode)) {
                                respCode = "0";

                                // 解析文件
                                String billUrl = tmpBkReader.getFirstText("/AIPG/BODY/DOWN_RSP/URL");
                                WriteBankLogLn2("待下载对账单文件链接:\r\n" + billUrl);

                                String filePath = createTempFileDirectory() + tmpBkReader.getFirstText("/AIPG/BODY/DOWN_RSP/FILENAME");
                                WriteBankLogLn2("账单下载后保存到本地路径: " + filePath);

                                smsGet(billUrl, filePath);

                                if (new File(filePath).exists()) {
                                    String billContent = FileHelper.readFileText(filePath, getCharset());
                                    WriteBankLogLn2("对账单明细内容:\r\n" + billContent);

                                    StringReader strReader = new StringReader(billContent);
                                    BufferedReader tmpReader = new BufferedReader(strReader);
                                    tmpReader.readLine();

                                    while (true) {
                                        String eachline = tmpReader.readLine();
                                        if (eachline == null) {
                                            break;
                                        }
                                        String[] detailNodes = eachline.split("\\|@\\|");
                                        if ("0000".equals(detailNodes[2])) {
                                            RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();

                                            if ("S".equals(p_reqQrySttm.statementType) && "0".equals(detailNodes[10])) {
                                                continue;
                                            }

                                            if ("F".equals(p_reqQrySttm.statementType) && "1".equals(detailNodes[10])) {
                                                continue;
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[0])) {
                                                tmpRetDetail.reqBatchNO = detailNodes[0];
                                                tmpRetDetail.askNumber = detailNodes[1];
                                            } else {
                                                tmpRetDetail.askNumber = detailNodes[1];
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[7]) && StringHelper.hasAnyChar(detailNodes[9]) && ("100001".equals(detailNodes[9]) || "100002".equals(detailNodes[9]))) {
                                                tmpRetDetail.askNumber = detailNodes[7];
                                            }

                                            if (StringHelper.isNullOrEmpty(detailNodes[7]) && StringHelper.hasAnyChar(detailNodes[9]) && ("100011".equals(detailNodes[9]) || "100014".equals(detailNodes[9]))) {
                                                tmpRetDetail.askNumber = detailNodes[0];
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[3])) {
                                                tmpRetDetail.amount = StringHelper.amountDivide100(detailNodes[3]);
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[5])) {
                                                tmpRetDetail.busTime = detailNodes[5];
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[4])) {
                                                tmpRetDetail.oppAct = detailNodes[4];
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[12])) {
                                                tmpRetDetail.bankOrderNo = detailNodes[12];
                                            }

                                            if (StringHelper.hasAnyChar(detailNodes[8])) {
                                                tmpRetDetail.fee = StringHelper.amountDivide100(detailNodes[8]);
                                            }
                                            //收
                                            if (StringHelper.hasAnyChar(detailNodes[10]) && "1".equals(detailNodes[10])) {
                                                tmpRetDetail.cdFlag = "22";
                                            }
                                            //付
                                            if (StringHelper.hasAnyChar(detailNodes[10]) && "0".equals(detailNodes[10])) {
                                                tmpRetDetail.cdFlag = "27";
                                            }

                                            tmpRetDetail.transState = TransState.Success;

                                            retAts.writeRetDetail(tmpRetDetail);
                                            totalNum++;
                                        }
                                    }
                                } else {
                                    respCode = "-1";
                                    respInfo = "文件下载失败!";
                                }
                            } else if ("1000".equalsIgnoreCase(tmpRetCode)) {
                                respCode = "0";
                                respInfo = tmpRetMsg;
                            } else {
                                respCode = "-1";
                                respInfo = tmpRetMsg;
                            }
                        } else {
                            respCode = "-1";
                            respInfo = tmpSbMsg.toString();
                        }
                    } else if (tmpStrRet[0].equals(ConnState.FAIL) || tmpStrRet[0].equals(FailCode.E9981)) {
                        respCode = "0";
                        respInfo = tmpStrRet[1];
                    } else {
                        respCode = "-1";
                        respInfo = tmpStrRet[1];
                    }
                } else {//
                    String settDay = Format.Date8Format.format(p_reqQrySttm.getBusDate());
                    String reqTime = Format.DateTime14Format.format(p_reqQrySttm.getBusDate());

                    String contentFee = "0"; /* 是否包含手续费 (0.不需手续费，1.包含手续费 ,空则默认为0) */
                    if (StringHelper.hasAnyChar(getBankConfig().getValueAsString("contFeeType"))) {
                        contentFee = getBankConfig().getValueAsString("contFeeType");
                    }

                    String merId = actItem.merchantId;
                    String sign = "";

                    // 签名数据
                    StringBuilder waitSignData = new StringBuilder();


                    waitSignData.append(settDay).append("|");
                    waitSignData.append(reqTime).append("|");
                    waitSignData.append(merId);
                /*if (StringHelper.hasAnyChar(actItem.qryStatementURL)) {
                    waitSignData.append(merId).append("|");
                    waitSignData.append(p_reqQrySttm.actNum);
                } else {
                    waitSignData.append(merId);
                }*/

                    WriteBankLogLn2("通联代收付(单笔、批量)对账单签名数据:\r\n" + waitSignData.toString());

                    StringBuilder tmpSb = new StringBuilder();
                    sign = signMessage(waitSignData.toString(), actItem, tmpSb);

                    StringBuilder reqSendData = new StringBuilder();

                    reqSendData.append("SETTDAY=").append(settDay);
                    reqSendData.append("&REQTIME=").append(reqTime);
                    reqSendData.append("&CONTFEE=").append(contentFee);
                    reqSendData.append("&MERID=").append(merId);
                    if (StringHelper.hasAnyChar(actItem.qryStatementURL)) {
                        reqSendData.append("&SETTACCT=").append(p_reqQrySttm.actNum);
                    }
                    reqSendData.append("&SIGN=").append(sign);

                    WriteBankLogLn2("通联代收付(单笔、批量)对账单请求数据:\r\n" + reqSendData.toString());

                    String payRecStatementURL = bankFront.getUrl("payRecStatement");
                    if (StringHelper.hasAnyChar(actItem.qryStatementURL)) {
                        payRecStatementURL = actItem.qryStatementURL;
                    }
                    WriteBankLogLn2("通联代收付(单笔、批量)对账单服务地址:" + payRecStatementURL);

                    String tmpRetStr = sendPayRecStatement(payRecStatementURL, reqSendData.toString());

                    WriteBankLogLn2("通联代收付对账单响应数据:\r\n" + tmpRetStr);

                    if (StringHelper.hasAnyChar(tmpRetStr)) {
                        respCode = "0";

                        StringReader strReader = new StringReader(tmpRetStr);
                        BufferedReader tmpReader = new BufferedReader(strReader);
                        tmpReader.readLine();

                        // 解析明细返回
                        while (true) {
                            String eachline = tmpReader.readLine();
                            if (StringHelper.isNullOrEmpty(eachline)) {
                                break;
                            }

                            RetAtsStatementDetail tmpRetDetail = null;

                            String[] detailNodes = eachline.split(" ");
                            if (StringHelper.hasAnyChar(detailNodes[3])) {
                                if ("0000".equals(detailNodes[3]) || "4000".equals(detailNodes[3])) {
                                    if ("F".equals(p_reqQrySttm.statementType)) {
                                        if ("0".equals(detailNodes[2])) {
                                            totalNum++;
                                            tmpRetDetail = writeDetailMsg(detailNodes);
                                        }
                                    } else if ("S".equals(p_reqQrySttm.statementType)) {
                                        if ("1".equals(detailNodes[2])) {
                                            totalNum++;
                                            tmpRetDetail = writeDetailMsg(detailNodes);
                                        }
                                    } else {
                                        totalNum++;
                                        tmpRetDetail = writeDetailMsg(detailNodes);
                                    }

                                    if (tmpRetDetail != null) {
                                        retAts.writeRetDetail(tmpRetDetail);
                                    }
                                }
                            }
                        }
                    } else {
                        respCode = "-1";
                        respInfo = "通联响应内容为空";
                    }
                }
            } else {
                respCode = "-1";
                respInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            respCode = "-1";
            respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        respHeader[0] = respCode;
        respHeader[1] = respInfo;

        return respHeader;
    }

    private String[] getTrxFileStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws
            Exception {
        String[] respHeader = new String[]{"", ""};

        String respCode = "";
        String respInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "unifiedorder");
            if (actItem != null) {
                TreeMap<String, String> params = new TreeMap<String, String>();
                params.put("cusid", actItem.merchantId);
                params.put("appid", actItem.appId);
                params.put("date", Format.Date8Format.format(p_reqQrySttm.getBusDate()));
                params.put("randomstr", get_nonce_str());
                String signMsg = sign(params, actItem.saltKey);
                params.put("sign", signMsg);

                String tmpRetStr = sendUnifiedToBank(params, bankFront.getUrl("trxFileStatement"));

                if (StringHelper.hasAnyChar(tmpRetStr)) {
                    if (tmpRetStr.indexOf("{") >= 0) {
                        JSONObject respJson = JSONObject.parseObject(tmpRetStr);
                        String retCode = respJson.getString("retcode");
                        if ("SUCCESS".equals(retCode)) {
                            String tmpRespFileURL = respJson.getString("url");//对账文件下载地址
                            WriteBankLogLn2("待下载文件链接:" + tmpRespFileURL);
                            String decodeURL = URLDecoder.decode(tmpRespFileURL, "UTF-8");
                            String fileName = tmpRespFileURL.substring(decodeURL.lastIndexOf("/") + 1);
                            String localFilePath = createTempFileDirectory() + File.separator + fileName;
                            WriteBankLogLn2("文件下载后存储本地文件路径:" + localFilePath);
                            SendBankRespose retResp = csvGet(tmpRespFileURL, localFilePath, p_reqQrySttm);
                            WriteBankLogStep3(retResp);
                            if (retResp.connState == "") {
                                String respStr = retResp.retMessage;

                                StringReader strReader = new StringReader(respStr);
                                BufferedReader tmpReader = new BufferedReader(strReader);

                                String line1 = tmpReader.readLine();
                                String[] columns = line1.split(",");

                                while (true) {
                                    String eachline = tmpReader.readLine();
                                    if (eachline == null) {
                                        break;
                                    }
                                    String[] values = eachline.split(",");
                                    if (columns.length == values.length) {
                                        HashMap<String, String> mapKV = SplitHelper.splitAsValueMap(columns, values);
                                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();
                                        totalNum++;
                                        //商户号,门店名称,终端号 ,交易时间,交易类型,交易批次号,凭证号,参考号,卡号,卡类别,发卡行机构代码,发卡行名称,交易金额,手续费,交易日期,交易单号,订单号,商户备注,对接应用号,原始金额,结算金额,产品类型
                                        if (mapKV.containsKey("交易金额")) {
                                            tmpRetDetail.amount = mapKV.get("交易金额").replace("`", "").trim();
                                        }
                                        if (mapKV.containsKey("交易日期") && mapKV.containsKey("交易时间")) {
                                            tmpRetDetail.busTime = mapKV.get("交易日期").replace("`", "").replace("-", "") + mapKV.get("交易时间").replace("`", "").replace(":", "");
                                        }
                                        if (mapKV.containsKey("交易单号")) {
                                            tmpRetDetail.askNumber = mapKV.get("交易单号").replace("`", "").trim();
                                        }
                                        if (mapKV.containsKey("参考号")) {
                                            tmpRetDetail.bkSeq = mapKV.get("参考号").replace("`", "").trim();
                                        }
                                        if (mapKV.containsKey("备注")) {
                                            tmpRetDetail.memo = mapKV.get("备注").replace("`", "").trim();
                                        }
                                        if (mapKV.containsKey("交易类型")) {
                                            tmpRetDetail.busType = mapKV.get("交易类型").replace("`", "").trim();
                                        }
                                        tmpRetDetail.transState = TransState.Success;
                                        retAts.writeRetDetail(tmpRetDetail);
                                    } else {
                                        break;
                                    }
                                }
                            } else {
                                respCode = "-1";
                                respInfo = retResp.retMessage;
                            }

                        } else {
                            respCode = "-1";
                            respInfo = respJson.getString("retmsg");
                        }
                    } else {
                        respCode = "-1";
                        respInfo = tmpRetStr;
                    }
                } else {
                    respCode = "-1";
                    respInfo = "通联响应数据为空";
                }
            } else {
                respCode = "-1";
                respInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            respCode = "-1";
            respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        respHeader[0] = respCode;
        respHeader[1] = respInfo;

        return respHeader;
    }

    private RetAtsStatementDetail writeDetailMsg(String[] detailNodes) {
        RetAtsStatementDetail retDetail = new RetAtsStatementDetail();

        // 商户订单号
        if (detailNodes.length > 8) {
            if (StringHelper.hasAnyChar(detailNodes[8]) && detailNodes[8] != detailNodes[0]) {
                retDetail.reqBatchNO = detailNodes[0];
                retDetail.askNumber = detailNodes[8];
            } else {
                retDetail.reqBatchNO = detailNodes[0];
                if (!"0".equals(detailNodes[1])) {
                    retDetail.askNumber = StringHelper.joinNotEmpty("_", detailNodes[0], detailNodes[1]);
                } else {
                    retDetail.askNumber = detailNodes[0];
                }
            }
        } else {
            retDetail.askNumber = detailNodes[0];
        }

        // 交易时间
        if (StringHelper.hasAnyChar(detailNodes[6])) {
            retDetail.busTime = detailNodes[6];
        }

        if (StringHelper.hasAnyChar(detailNodes[2])) {
            String busType = detailNodes[2];
            if ("0".equals(busType)) {
                retDetail.cdFlag = "27";
            } else {
                retDetail.cdFlag = "22";
            }
        }

        // 交易金额
        if (StringHelper.hasAnyChar(detailNodes[4])) {
            retDetail.amount = StringHelper.amountDivide100(detailNodes[4]);
        }

        // 对方账号
        if (StringHelper.hasAnyChar(detailNodes[5])) {
            retDetail.oppAct = detailNodes[5];
        }

        // 手续费
        if (detailNodes.length > 9) {
            if (StringHelper.hasAnyChar(detailNodes[9])) {
                retDetail.fee = StringHelper.amountDivide100(detailNodes[9]);
            }
        }

        retDetail.transState = TransState.Success;

        return retDetail;
    }

    /**
     * POS收款对账单获取
     *
     * @param p_reqQrySttm
     * @param retAts
     * @return
     * @throws Exception
     */
    private String[] getPosRecStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws
            Exception {
        String[] respHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            if (StringHelper.isNullOrEmpty(p_reqQrySttm.channel)) {
                ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "pos");
                if (actItem == null) {
                    respHeader[0] = "-1";
                    respHeader[1] = "未找到账号:[" + p_reqQrySttm.actNum + "]商户配置信息!";
                    return respHeader;
                }
            }

            FtpSet ftpSet = bankFront.getFtpSet("pos");
            ftpSet.downDir = StringHelper.trimEnd(ftpSet.getDownDir("pos"), "/") + "/" + p_reqQrySttm.busDate;
            WriteBankLogLn2("通联POS对账单FTP服务器地址:" + ftpSet.serverIP + ":" + ftpSet.port);

            StringBuilder sbFileContent = new StringBuilder();

            String tmpPosMode = getBankConfig().getValueAsString("posRecUseVersion");
            if ("A".equals(tmpPosMode)) {
                String[] provinceArray = null;
                String provinceList = getBankConfig().getValueAsString("provinceList");
                if (provinceList.contains(",")) {
                    provinceArray = provinceList.split(",");
                }
                for (String tmpProvince : provinceArray) {
                    String downFileName = getBankConfig().getValueAsString("merchantId") + p_reqQrySttm.busDate + tmpProvince + ".txt";
                    WriteBankLogLn2("通联POS对账单所在服务器路径:" + ftpSet.downDir + "/" + downFileName);

                    String localFilePath = createTempFileDirectory() + File.separator + downFileName;
                    WriteBankLogLn2("通联POS对账单保存本地路径:" + localFilePath);

                    FtpReceiver ftpReceiver = null;
                    String posRecRequestType = getBankConfig().getValueAsString("posRecRequestType");
                    if ("ftp".equals(posRecRequestType.toLowerCase())) {
                        FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
                        ftpReceiver = ftpPortClient.downloadFile(downFileName, localFilePath);
                    } else if ("sftp".equals(posRecRequestType.toLowerCase())) {
                        SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
                        String sftpFilePath = StringHelper.trimEnd(ftpSet.downDir, "/") + "/" + downFileName;
                        WriteBankLogLn2("待下载SFTP服务器文件路径:\r\n" + sftpFilePath);
                        ftpReceiver = sftpPortClient.downloadFile("", sftpFilePath, localFilePath);
                    }
                    if (ftpReceiver.isCompleted) {
                        if (sbFileContent.length() > 0) {
                            sbFileContent.append("\n");
                        }
                        sbFileContent.append(FileHelper.readFileText(localFilePath, getCharset("UTF-8", "pos")));
                    } else {
                        tmpRespCode = "-1";
                        tmpRespInfo = "通联POS对账单下载失败,原因:\r\n" + ftpReceiver.connMsg;
                    }
                }
            } else if ("B".equals(tmpPosMode)) {
                String downFileName = p_reqQrySttm.actNum + p_reqQrySttm.busDate + ".txt";
                WriteBankLogLn2("通联POS对账单所在服务器路径:" + ftpSet.downDir + "/" + downFileName);

                String localFilePath = createTempFileDirectory() + File.separator + downFileName;
                WriteBankLogLn2("通联POS对账单保存本地路径:" + localFilePath);

                FtpReceiver ftpReceiver = null;
                String posRecRequestType = getBankConfig().getValueAsString("posRecRequestType");
                if ("ftp".equals(posRecRequestType.toLowerCase())) {
                    FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
                    ftpReceiver = ftpPortClient.downloadFile(downFileName, localFilePath);
                } else if ("sftp".equals(posRecRequestType.toLowerCase())) {
                    SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
                    String sftpFilePath = StringHelper.trimEnd(ftpSet.downDir, "/") + "/" + downFileName;
                    WriteBankLogLn2("待下载SFTP服务器文件路径:\r\n" + sftpFilePath);
                    ftpReceiver = sftpPortClient.downloadFile("", sftpFilePath, localFilePath);
                }
                if (ftpReceiver.isCompleted) {
                    if (sbFileContent.length() > 0) {
                        sbFileContent.append("\n");
                    }
                    sbFileContent.append(FileHelper.readFileText(localFilePath, getCharset("UTF-8", "pos")));
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = "通联POS对账单下载失败,原因:\r\n" + ftpReceiver.connMsg;
                }
            } else {
                tmpRespCode = "-1";
                tmpRespInfo = "对账单版本错误,当前版本为:[" + tmpPosMode + "].";
            }

            if (StringHelper.hasAnyChar(sbFileContent.toString())) {
                String tmpStrRet = sbFileContent.toString();
                WriteBankLogLn2("通联POS对账单响应数据:\r\n" + tmpStrRet);

                tmpRespCode = "0";
                boolean isContinue = false;

                StringReader strReader = new StringReader(tmpStrRet);
                BufferedReader tmpReader = new BufferedReader(strReader);

                while (true) {
                    String eachline = tmpReader.readLine();
                    if (eachline == null) {
                        break;
                    }
                    if ("".equals(eachline.trim())) {
                        continue;
                    }
                    String[] detailNodes = eachline.split("`~");
                    if (p_reqQrySttm.actNum.equals(detailNodes[1].trim())) {
                        totalNum++;
                        isContinue = true;
                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();

                        if (StringHelper.hasAnyChar(detailNodes[4])) {
                            tmpRetDetail.askNumber = detailNodes[4].trim();
                        }

                        tmpRetDetail.cdFlag = "22";

                        if (StringHelper.hasAnyChar(detailNodes[11])) {
                            tmpRetDetail.amount = StringHelper.amountDivide100(detailNodes[11].trim());
                        }

                        if (StringHelper.hasAnyChar(detailNodes[15])) {
                            tmpRetDetail.fee = StringHelper.amountDivide100(detailNodes[15].trim());
                        }

                        tmpRetDetail.busTime = detailNodes[6];

                        if (StringHelper.hasAnyChar(detailNodes[7])) {
                            tmpRetDetail.oppAct = detailNodes[7].trim();
                        }

                        if (StringHelper.hasAnyChar(detailNodes[8])) {
                            tmpRetDetail.oppActName = detailNodes[8].trim();
                        }

                        if ("2".equals(detailNodes[13].trim())) {
                            tmpRetDetail.transState = TransState.Success;
                        } else {
                            tmpRetDetail.transState = TransState.Fail;
                        }

                        retAts.writeRetDetail(tmpRetDetail);
                    }
                }

                if (!isContinue) {
                    tmpRespCode = "0";
                    tmpRespInfo = "没有符合条件的记录!";
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        respHeader[0] = tmpRespCode;
        respHeader[1] = tmpRespInfo;

        return respHeader;
    }
}
